﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Microsoft.Drawing;
using System.Drawing.Imaging;

namespace WiMo.Games.Premium.GDIDisplay.ImageAPI
{
    static partial class GraphicsExtension
    {
        public static void DrawRectangle(this Graphics gx, WiMo.Games.Size size, Color borderColor, Color backColor, System.Drawing.Size borderRadius, byte transparency)
        {
            DrawRectangle(gx, new WiMo.Games.Rectangle(0, 0, size.Width, size.Height), borderColor, backColor, borderRadius, transparency);
        }

        private static Point[] GetPoints(WiMo.Games.Rectangle rc, System.Drawing.Size radius)
        {
            var points = new Point[8];
            //prepare points for poligon
            points[0].X = rc.Left + radius.Width / 2;
            points[0].Y = rc.Top + 1;
            points[1].X = rc.Right - radius.Width / 2;
            points[1].Y = rc.Top + 1;

            points[2].X = rc.Right;
            points[2].Y = rc.Top + radius.Height / 2;
            points[3].X = rc.Right;
            points[3].Y = rc.Bottom - radius.Height / 2;

            points[4].X = rc.Right - radius.Width / 2;
            points[4].Y = rc.Bottom;
            points[5].X = rc.Left + radius.Width / 2;
            points[5].Y = rc.Bottom;

            points[6].X = rc.Left + 1;
            points[6].Y = rc.Bottom - radius.Height / 2;
            points[7].X = rc.Left + 1;
            points[7].Y = rc.Top + radius.Height / 2;

            return points;
        }

        public static void DrawRectangle(this Graphics g, WiMo.Games.Rectangle rc, Color borderColor, Color backColor, System.Drawing.Size radius)
        {
            DrawRectangle(g, rc, borderColor, 1, backColor, radius);
        }

        
        public static void DrawRectangle(this Graphics g, WiMo.Games.Rectangle rc, Color borderColor, int borderWidth, Color backColor, System.Drawing.Size radius)
        {
            var points = GetPoints(rc, radius);
            using (var p = new Pen(borderColor.ToDrawingColor(), borderWidth))
            {
                using (var fillBrush = new SolidBrush(backColor.ToDrawingColor()))
                {
                    //draw side lines and circles in the corners
                    g.DrawLine(p, rc.Left + radius.Width / 2, rc.Top, rc.Right - radius.Width / 2, rc.Top);
                    g.FillEllipse(fillBrush, rc.Right - radius.Width, rc.Top, radius.Width, radius.Height);
                    g.DrawEllipse(p, rc.Right - radius.Width, rc.Top, radius.Width, radius.Height);
                    g.DrawLine(p, rc.Right, rc.Top + radius.Height / 2, rc.Right, rc.Bottom - radius.Height / 2);
                    g.FillEllipse(fillBrush, rc.Right - radius.Width, rc.Bottom - radius.Height, radius.Width, radius.Height);
                    g.DrawEllipse(p, rc.Right - radius.Width, rc.Bottom - radius.Height, radius.Width, radius.Height);
                    g.DrawLine(p, rc.Right - radius.Width / 2, rc.Bottom, rc.Left + radius.Width / 2, rc.Bottom);
                    g.FillEllipse(fillBrush, rc.Left, rc.Bottom - radius.Height, radius.Width, radius.Height);
                    g.DrawEllipse(p, rc.Left, rc.Bottom - radius.Height, radius.Width, radius.Height);
                    g.DrawLine(p, rc.Left, rc.Bottom - radius.Height / 2, rc.Left, rc.Top + radius.Height / 2);
                    g.FillEllipse(fillBrush, rc.Left, rc.Top, radius.Width, radius.Height);
                    g.DrawEllipse(p, rc.Left, rc.Top, radius.Width, radius.Height);

                    //fill the background and remove the internal arcs  
                    g.FillPolygon(fillBrush, points);
                }
            }
        }

        private static Bitmap GetMask(WiMo.Games.Rectangle rc, Color borderColor, System.Drawing.Size radius, Color colorKey)
        {
            var bitmap = new Bitmap(rc.Width + 1, rc.Height + 1);

            using (var graphics = Graphics.FromImage(bitmap))
            {
                graphics.Clear(colorKey.GetInverted().ToDrawingColor());
                DrawRectangle(graphics, rc, borderColor, colorKey, radius);
            }

            return bitmap;
        }

        public static void FillRectangle(this Graphics gx, WiMo.Games.Size size, Color backColor)
        {
            FillRectangle(gx, new WiMo.Games.Rectangle(0,0,size.Width, size.Height), backColor);
        }

        public static void FillRectangle(this Graphics gx, WiMo.Games.Rectangle rc, Color backColor)
        {
            DrawRectangle(gx, rc, Color.Transparent, 0, backColor, 0xff);
        }

        public static void DrawRectangle(this Graphics gx, WiMo.Games.Rectangle rc, Color borderColor)
        {
            DrawRectangle(gx, rc, borderColor, 1, Color.Transparent, 0xff);
        }

        public static void DrawRectangle(this Graphics gx, WiMo.Games.Rectangle rc, Color borderColor, Color backColor)
        {
            DrawRectangle(gx, rc, borderColor, 1, backColor, 0xff);
        }

        public static void DrawRectangle(this Graphics gx, WiMo.Games.Rectangle rc, Color borderColor, Color backColor, byte transparency)
        {
            DrawRectangle(gx, rc, borderColor, 1, backColor, transparency);
        }

        public static void DrawRectangle(this Graphics gx, WiMo.Games.Rectangle rc, Color borderColor, int borderWidth, Color backColor, byte transparency)
        {
            if (transparency < 0xFF)
            {
                using (var tempBitmap = new Bitmap(rc.Width, rc.Height))
                {
                    using (var tempGraphics = Graphics.FromImage(tempBitmap))
                    {
                        if (backColor != Color.Transparent)
                            using (var backColorBrush = new SolidBrush(backColor.ToDrawingColor()))
                                tempGraphics.FillRectangle(backColorBrush, new System.Drawing.Rectangle(0, 0, rc.Width, rc.Height));

                        if (borderColor != Color.Transparent)
                            using (var borderPen = new Pen(borderColor.ToDrawingColor()))
                                tempGraphics.DrawRectangle(borderPen, new System.Drawing.Rectangle(0, 0, rc.Width, rc.Height));

                        gx.DrawAlpha(tempBitmap, transparency, rc.X, rc.Y);
                    }
                }
            }
            else
            {
                if (backColor != Color.Transparent)
                    using (var backColorBrush = new SolidBrush(backColor.ToDrawingColor()))
                        gx.FillRectangle(backColorBrush, new System.Drawing.Rectangle(0, 0, rc.Width, rc.Height));

                if (borderColor != Color.Transparent)
                    using (var borderPen = new Pen(borderColor.ToDrawingColor()))
                        gx.DrawRectangle(borderPen, new System.Drawing.Rectangle(0, 0, rc.Width, rc.Height));
            }
        }

        public static void DrawRectangle(this Graphics gx, WiMo.Games.Rectangle rc, Color borderColor, Color backColor, System.Drawing.Size borderRadius, byte alpha)
        {
            DrawRectangle(gx, rc, borderColor, backColor, backColor, borderRadius, alpha);
        }

        public static void DrawRectangle(this Graphics gx, WiMo.Games.Rectangle rc, Color borderColor, Color startColor, Color endColor, System.Drawing.Size radius, byte alpha)
        {
            using (var image = new Bitmap(rc.Width, rc.Height))
            {
                using (var graphics = Graphics.FromImage(image))
                {
                    var roundedRect = new WiMo.Games.Rectangle(0, 0, rc.Width, rc.Height);

                    if (startColor != endColor)
                        GradientFill.Fill(graphics, roundedRect.ToDrawingRect(), startColor.ToDrawingColor(), endColor.ToDrawingColor(), FillDirection.TopToBottom);
                    else
                        graphics.Clear(startColor.ToDrawingColor());
                    
                    //tempGx.DrawAlpha(gradientImage, alpha, rc.X, rc.Y);

                    //gxGradient.DrawImage(tempBitmap, new System.Drawing.Rectangle(0, 0, rc.Width, rc.Height), rc.ToDrawingRect(), GraphicsUnit.Pixel);

                    roundedRect.Width--;
                    roundedRect.Height--;

                    var maskColor = (borderColor + startColor) / 2;
    
                    using (var rectMask = GetMask(roundedRect, borderColor, radius, maskColor))
                        graphics.DrawImage(rectMask, new Location(0, 0), maskColor);

                    gx.Clear(System.Drawing.Color.BlueViolet);
                    gx.DrawImage(image, rc);
                }
            }
        }
    }
}
